#pragma once

#include <string>

#include "utils/SafeCast.h"
#include "TagStorage.h"
#include "DirectoryWatch.h"


// class TagSourceSolution : public TagSource{
// public:
// 	TagSourceSolution(const char* slnFileName);
// };


class TagSourceDirectory;
class TagNodeDirectory : public TagNode, public DirectoryWatch{
public:
    TagNodeDirectory(TagNodeDirectory* parent);
    TagNodeDirectory(TagSourceDirectory* source);

	bool onFileAdded(const char* name);
	bool onFileRemoved(const char* name);
	bool onFileRenamed(const char* oldName, const char* newName);
	bool onFileModified(const char* name);

	bool attach(const char* path, bool root = false);
	TagSourceDirectory* source(){ return source_; }
	bool poll();

	TagNodeDirectory* parent(){ return safe_cast<TagNodeDirectory*>(TagNode::parent()); }
protected:
	TagSourceDirectory* source_;
};

class TagNodeFile : public TagNode{
public:
    TagNodeFile(TagNodeDirectory* parent);
	TagNodeDirectory* parent() { return static_cast<TagNodeDirectory*>(TagNode::parent()); }
	bool attach(const char* path);
	bool rescan();
protected:
	std::string path_;
};

class TagSourceDirectory : public TagSource, public DirectoryListener{
public:
	TagSourceDirectory(TagStorage* storage, const char* root);
	~TagSourceDirectory();

	void onFileAdded(DirectoryWatch* watch, const char* path);
	void onFileRemoved(DirectoryWatch* watch, const char* path);
	void onFileModified(DirectoryWatch* watch, const char* path);
	void onFileRenamed(DirectoryWatch* watch, const char* oldName, const char* newName);

	bool poll();

	const char* tagFilePath() const{ return tagFilePath_.c_str(); }
protected:
	TagNode* findNodeByPath(const char* path, bool filePath = true);

	void rescan();

	bool changed_;
	DirectoryWatch* directoryWatch_;
	std::string tagFilePath_;
	TagNodeDirectory directory_;
};
